package com.syh.jn.scm.infrastructure.repository.impl.supplier.stock;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.spring.SpringContextUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AggregateRepoHibernateImplTmpl;
import com.syh.jn.scm.domain.supplier.entity.logistics.LogisticsBill;
import com.syh.jn.scm.domain.supplier.entity.stock.StockRecord;
import com.syh.jn.scm.domain.supplier.entity.stock.StockRecordItem;
import com.syh.jn.scm.domain.supplier.repository.logistics.LogisticsBillRepository;
import com.syh.jn.scm.domain.supplier.repository.stock.StockRecordRepository;
import com.syh.jn.scm.dto.supplier.stock.StockRecordItemVo;
import com.syh.jn.scm.exception.BusinessException;
import com.syh.jn.scm.infrastructure.repository.model.base.StorehouseModel;
import com.syh.jn.scm.infrastructure.repository.model.logistics.LogisticsBillModel;
import com.syh.jn.scm.infrastructure.repository.model.stock.StockRecordItemModel;
import com.syh.jn.scm.infrastructure.repository.model.stock.StockRecordModel;
import com.syh.jn.scm.service.api.supplier.logistics.enums.LogisticsBillEnums;
import lombok.extern.java.Log;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 出入库记录
 */
@Log
@Repository
public class StockRecordRepositoryImpl implements StockRecordRepository {

  private HibernateTemplate hibernateTemplate;

  private AggregateRepoHibernateImplTmpl<StockRecord, StockRecordModel, Long> stockRecordRepoHibernateImplTmpl;
  private AggregateRepoHibernateImplTmpl<StockRecordItem, StockRecordItemModel, Long> stockRecordItemsRepoHibernateImplTmpl;

  @Autowired
  public StockRecordRepositoryImpl(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
    stockRecordRepoHibernateImplTmpl =
            new AggregateRepoHibernateImplTmpl.Builder().hibernateTemplate(hibernateTemplate).idClass(Long.class).entityClass(StockRecord.class).modelClass(StockRecordModel.class).build();
    stockRecordItemsRepoHibernateImplTmpl =
            new AggregateRepoHibernateImplTmpl.Builder().hibernateTemplate(hibernateTemplate).idClass(Long.class).entityClass(StockRecordItem.class).modelClass(StockRecordItemModel.class).build();
  }

  /**
   * 重写add方法
   *
   * @param stockRecord
   * @return
   */
  @Override
  public Long add(StockRecord stockRecord) {
    //保存出入库记录基础信息
    StockRecordModel add = stockRecordRepoHibernateImplTmpl.add(stockRecord);
    Long id = add.getId();
    //保存出库人记录子项
    this.saveStockRecordItems(id, stockRecord.getItems());
    return id;
  }

  /**
   * 根据出入库记录id获取出入库记录项
   *
   * @param stockRecordId
   * @return
   */
  @Override
  public List<StockRecordItemVo> findStockRecordItemsByStockRecordId(Long stockRecordId) {
    List<StockRecordItemModel> stockRecordItemModels = this.getItemsById(stockRecordId);

    //转换格式：Model转Vo
    List<StockRecordItemVo> stockRecordItemVos = new ArrayList<>();
    stockRecordItemModels.stream().forEach(stockRecordItemModel -> {
      StockRecordItemVo stockRecordItemVo = new StockRecordItemVo();
      ExtBeanUtils.copyProperties(stockRecordItemModel, stockRecordItemVo);

      stockRecordItemVos.add(stockRecordItemVo);
    });

    return stockRecordItemVos;
  }

  @Override
  public boolean stockRecordItemExistsById(String column, Long id) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq(column, id));
    return this.stockRecordItemsRepoHibernateImplTmpl.getOne(wrapper) != null;
  }

  /**
   * 根据出入库记录id获取出入库记录项
   *
   * @param wrapper
   * @param startRow
   * @param count
   * @return
   */
  @Override
  public List<StockRecordItemVo> findStockRecordItemListPage(Wrapper wrapper, Integer startRow, Integer count) {
    log.warning("该接口暂不实现");
    return Collections.EMPTY_LIST;
  }

  /**
   * 根据出入库记录id获取出入库记录项数量
   *
   * @param wrapper
   * @return
   */
  @Override
  public int findStockRecordItemListPageCount(Wrapper wrapper) {
    return this.stockRecordItemsRepoHibernateImplTmpl.getCount(wrapper);
  }

  /**
   * 保存出库人记录子项
   *
   * @param stockRecordId
   * @param items
   */
  private void saveStockRecordItems(Long stockRecordId, List<StockRecordItem> items) {
    items.stream().forEach(item -> {
      StockRecordItemModel stockRecordItemModel = new StockRecordItemModel();
      ExtBeanUtils.copyProperties(item, stockRecordItemModel);
      //维护出入库记录id
      stockRecordItemModel.setRecordOrderId(stockRecordId);
      //保存子项
      this.hibernateTemplate.save(stockRecordItemModel);
    });
  }

  /**
   * 删除出库人记录子项
   *
   * @param stockRecordId
   */
  private void delItemsById(Long stockRecordId) {
    List<StockRecordItemModel> stockRecordItems = this.getItemsById(stockRecordId);

    stockRecordItems.stream().forEach(item -> {
      this.hibernateTemplate.delete(item);
    });
  }

  @Override
  public StockRecord getById(Long aLong) {
    return stockRecordRepoHibernateImplTmpl.getById(aLong);
  }

  @Override
  public StockRecord getOne(Wrapper wrapper) {
    StockRecord record = stockRecordRepoHibernateImplTmpl.getOne(wrapper);
    Wrapper we = Wrapper.build().append(Restrictions.eq("recordOrderId",record.getId()));
    List<StockRecordItem> items = stockRecordItemsRepoHibernateImplTmpl.getList(we);
    record.setItems(items);
    return record;
  }

  @Override
  public List<StockRecord> getList(Wrapper wrapper) {
    return stockRecordRepoHibernateImplTmpl.getList(wrapper);
  }

  @Override
  public List<StockRecord> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return stockRecordRepoHibernateImplTmpl.findListPage(wrapper, startRow, count);
  }

  @Override
  public int getCount(Wrapper wrapper) {
    return stockRecordRepoHibernateImplTmpl.getCount(wrapper);
  }

  @Override
  public boolean contains(Long aLong) {
    return stockRecordRepoHibernateImplTmpl.contains(aLong);
  }

  /**
   * 根据出入库记录id获取出入库记录项
   *
   * @param stockRecordId
   * @return
   */
  protected List<StockRecordItemModel> getItemsById(Long stockRecordId) {
    //获取库存项
    String hql = "FROM StockRecordItemModel model WHERE model.recordOrderId = ?";
    List<StockRecordItemModel> stockRecordItemModels = (List<StockRecordItemModel>) this.hibernateTemplate.find(hql, stockRecordId);

    return stockRecordItemModels;
  }

  @Override
  public StockRecord getByLogisticsBillId(Long bllId) {
    String hql = "FROM StockRecordModel model WHERE model.logisticsBillId = ?";
    StockRecord stockRecord = (StockRecord) this.hibernateTemplate.find(hql, bllId);
    return stockRecord;
  }

  @Override
  public void repairLogisticsBillEmptyDepot() {

    /**
    //查出仓库为null的物流订单
    String emptyDepotBill_hql = "from LogisticsBillModel where depotId is null";
    List<LogisticsBillModel> bills = (List<LogisticsBillModel>)this.hibernateTemplate.find(emptyDepotBill_hql);

    Set<Long> billBusinessEntityIds =
            bills.stream().map(bill ->{
              return bill.getBusinessEntityId();
            }).collect(Collectors.toSet());

     默认仓库字段已删除
    //根据主体id找到默认仓库，把仓库为null的物流订单设置仓库并保存
    billBusinessEntityIds.forEach(id ->{
      String depot_hql = "from StorehouseModel model where model.businessEntityId = ? ORDER BY model.isDefault DESC,model.type";
      List<StorehouseModel> depots = (List<StorehouseModel>)this.hibernateTemplate.find(depot_hql,id);

      List<LogisticsBillModel> businessBills =
              bills.stream().filter(bill ->{
                return bill.getBusinessEntityId().equals(id);
              }).collect(Collectors.toList());

      businessBills.forEach( bill ->{
//        if(depots == null || depots.isEmpty())
//          return;
        bill.setDepotId(depots.get(0).getId());
        this.hibernateTemplate.save(bill);
      });

    });
  */
    throw new BusinessException("该方法已删除");
  }

  @Override
  public void generateStockRecordAtNull() {

    //查出不存在库存记录的物流单据
    String logis_hql = "FROM LogisticsBillModel logis WHERE logis.id not in(select originalLogisticsId from StockRecordModel record WHERE originalLogisticsId IS NOT NULL) AND ((logis.orderType = 0 AND logis.logisticsState > 0) OR (logis.orderType = 2 AND logis.logisticsState = 2))";
    List<LogisticsBillModel> bills = (List<LogisticsBillModel>)this.hibernateTemplate.find(logis_hql);

    List<LogisticsBill> logisEntitys = new ArrayList<>();
    LogisticsBillRepository logisRepo = (LogisticsBillRepository) SpringContextUtils.getBean(LogisticsBillRepository.class);

    bills.stream().forEach(model ->{
      LogisticsBill entity = logisRepo.getById(model.getId());
      logisEntitys.add(entity);
    });

    //重新生成库存记录
    logisEntitys.forEach(bill ->{
      StockRecord stockRecord = new StockRecord();
      if(bill.getOrderType().equals(LogisticsBillEnums.OrderType.SALE.getStatus()) || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus())){
        stockRecord.delivery(bill);
        stockRecord.setCreateTimeStamp(bill.getDeliveryTimestamp());
      }
      else if(bill.getOrderType().equals(LogisticsBillEnums.OrderType.PURCHASE.getStatus()) || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_SALE.getStatus())){
        stockRecord.collect(bill);
        stockRecord.setCreateTimeStamp(bill.getStorageTimestamp());
      }
      this.add(stockRecord);
    });

  }

  /**
   * 根据服务商id删除出入库记录
   * @param businessEntityId
   */
  @Override
  public void deleteByBusinessEntityId(Long businessEntityId) {
    String itemHql = "delete from StockRecordItemModel where businessEntityId = :businessEntityId";
    Query itemQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(itemHql);
    itemQuery.setParameter("businessEntityId",businessEntityId);
    itemQuery.executeUpdate();
    String orderHql = "delete from StockRecordModel where businessEntityId = :businessEntityId";
    Query orderQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(orderHql);
    orderQuery.setParameter("businessEntityId",businessEntityId);
    orderQuery.executeUpdate();
  }
}
